home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
176-200
/
disk_188
/
fastgro
/
readme
< prev
next >
Wrap
Text File
|
1992-05-06
|
7KB
|
163 lines
FastGro 1.0
Copyright (c) 1989 Doug Houck
PUBLIC-DOMAIN-NOTICE-PUBLIC-DOMAIN-NOTICE-PUBLIC-DOMAIN-NOTICE-PUBLIC-DOMAIN
P N
P This program has been placed in the public domain, and so may N
P be copied by anyone for any purpose whatsoever. Enjoy! N
P N
PUBLIC-DOMAIN-NOTICE-PUBLIC-DOMAIN-NOTICE-PUBLIC-DOMAIN-NOTICE-PUBLIC-DOMAIN
WHAT DOES IT DO?
FastGro is a fractal program, simulating Diffusion-Limited
Aggregation (DLA). It was inspired by a column in Scientific American,
(Computer Recreations, December 1988) which described various
implementations of DLA. The program was called SLO GRO, and took about 4
to 5 hours to run. FastGro will do the same thing, only in 4 to 5 minutes!
To quote A. K. Dewdney, the author of the inspiring column,
"It all starts when SLO GRO places a single particle at the center of the
computer screen. A particle is then set on a random walk from a random
point on a large circle centered on the initial particle. After a long
and arduous journey the particle happens on the stationary particle and
stops. As soon as that happens SLO GRO will dispatch another particle
on a similar journey from another random point on the circle. Particle
after particle collects at the site of the original one and a strange
shape emerges within the circle: a treelike growth with oddly twisted
branches and twigs. The shape results from a tendency of a randomly
walking particle to run into an outer part of the crowd long before it
encounters a cohort much deeper in the crowd; twigs are more likely to
grow from branches than from the core, so to speak."
WHAT THE PROMPTS MEAN
FastGro needs three pieces of information: the size of the
cirle, the number of particles, and how often to change colors.
The acceptable range is given in parentheses (low..high), and the
default is in [brackets].
The RADIUS defines the maximum size of the fractal. Of course,
smaller ones take less time, whereas the largest take about an hour.
If you have a PAL screen, or use MoreRows, the radius can be bigger.
Note that a 16 color hires screen is used, so hiding it behind a lo-res
screen will speed up the drawing somewhat.
The fractal may be stopped after a given number of PARTICLES.
If too large a number is given, it will outline the bounding circle.
You may stop the drawing at any time by clicking on the drawing screen.
You may CHANGE COLOR AFTER a certain number of particles have
aggregated. A small number will give a mottled effect, while larger
numbers will give a banding effect, showing the order in which the
points were added.
FURTHER READING
"Random walks that lead to fractal crowds," A. K. Dewdney in Scientific
American, Vol. 259, No. 6, pages 88-91; December, 1988
"Fractal Growth," Leonard M. Sander in Scientific American, Vol. 256,
No. 1, pages 82-88; January, 1987
OPTIMIZATION & IMPLEMENTATION
The rest of this ReadMe is technical information for those who
would like to know how this program was optimized.
Calculation of Random Number for Direction
BEFORE direction = random
AFTER direction = random_array[index]
index = index + 1
The part of the program that does the random walk takes most of
the time, so it was there that I concentrated my efforts. A random number
is needed for every step of the particle's journey, and since generating
random numbers takes time, I simply generated an array of random numbers
when initializing, and thereafter simply scan through the array to get
the required direction. Generating the numbers is what takes the thirty
seconds at the beginning.
True, the numbers read from the array are not truly random.
But were they ever? Computer-generated random numbers are still
pseudo-random, no matter how many convolutions you go through. The $64k
question is, "Is it random enough for our purposes?" In this case, yes.
I use a large array (about 50K), and XOR each byte as I read it, which
seems to mix things up enough.
Calculation of Starting Points For Particles
BEFORE angle = random * 360
x = radius * cosine(angle) + x_offset
y = radius * sine(angle) + y_offset
AFTER index = random * NumberOfStartLocations
x = start[index].x
y = start[index].y
Each particle must be launched from a random point on the edge
of the circle. Rather than calculating the x,y coordinates from a
random angle while running, I have precalculated the coordinates for
reasonable number of points around the circle, and stored those in an
array. To get the starting point for a new particle, I simply get a
random index into the array, and recall those points. This saves doing
trigonometry while running.
Calculation of Distance from Center
BEFORE distx = x - x_offset
disty = y - y_offset
DistanceSquared = distx*distx + disty*disty
AFTER if border[x,y]
Some particles might wander out of the circle. Those should
be abandoned, and new particles selected. But how does one determine
if a particle wanders out? Determining the distance from the center
of the circle requires a multiplication - much too slow for us.
Instead, I create a two-dimensional array of bits, with bits set for
those points corresponding to the edge of the circle. So, to test
for the edge of the circle merely requires testing a bit. In effect,
I put a fence of bits around the working area.
Calculation of Particle Hit
BEFORE if particle[x+1,y] <> 0
or particle[x,y+1] <> 0
or particle[x-1,y] <> 0
or particle[x,y-1] <> 0
AFTER SetSurroundingBits( x, y )
...
if particle[x,y]
To detect when a particle hits a stationary particle, I use another
two-dimensional array, one bit for each pixel on the screen. Each time I
set a pixel on the screen, I do the same in my array, and also set the bits
surrounding it. To detect if I am next to a particle on the screen, I check
only the bit I am on in my array. If it is set, I am near a particle.
This is analogous to running a boat near the shore. When you start to hang
up on the sand, you know the shoreline is near. This is much faster than
checking all adjacent points at each step.
The two-dimensional bit arrays are set up with a one-dimensional
array of pointers to the rows. To get to a given coordinate requires
only a lookup in the pointer array, then adding an offset.
The routine that does the actual random walk is coded in assembly
language, so as to register-optimize it.
TRADEOFFS
Of course, optimizing for speed involves the usual tradeoff
with space. I use approximately 120K for arrays - space which may not
be available in lesser machines or languages. Total memory consumption,
including code and display screen, amounts to about 300k.